home *** CD-ROM | disk | FTP | other *** search
/ Isometric Game Programming with DirectX 7.0 / Isometric Game Programming.iso / source / chapter13 / isohex13_4 / tileset.cpp < prev    next >
C/C++ Source or Header  |  2000-06-19  |  8KB  |  364 lines

  1. // TileSet.cpp: implementation of the CTileSet class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4.  
  5. #include "TileSet.h"
  6.  
  7. //////////////////////////////////////////////////////////////////////
  8. // Construction/Destruction
  9. //////////////////////////////////////////////////////////////////////
  10.  
  11. CTileSet::CTileSet()
  12. {
  13.     //set all members to 0 or NULL
  14.     dwTileCount=0;
  15.     ptiTileList=NULL;
  16.     lpddsTileSet=NULL;
  17.     lpszReload=NULL;
  18. }
  19.  
  20. CTileSet::~CTileSet()
  21. {
  22.     //unload the tileset
  23.     Unload();
  24. }
  25.  
  26. //load(initializer)
  27. void CTileSet::Load(LPDIRECTDRAW7 lpdd,LPSTR lpszLoad)
  28. {
  29.     //unload any currently loaded tileset
  30.     Unload();
  31.  
  32.     //copy filename
  33.     lpszReload=strdup(lpszLoad);
  34.  
  35.     //load in the tileset
  36.     lpddsTileSet=LPDDS_LoadFromFile(lpdd,lpszReload);
  37.  
  38.  
  39.     //retrieve DDSURFACEDESC2 from surface
  40.     DDSURFACEDESC2 ddsd;
  41.     DDSD_Clear(&ddsd);
  42.     lpddsTileSet->GetSurfaceDesc(&ddsd);
  43.  
  44.     //copy width and height
  45.     int iWidth=ddsd.dwWidth;
  46.     int iHeight=ddsd.dwHeight;
  47.  
  48.     //temporary variables for cell walls
  49.     int* HCellWall=NULL;
  50.     int HCellWallCount=0;
  51.     int* VCellWall=NULL;
  52.     int VCellWallCount=0;
  53.     int xCount=0;
  54.     int yCount=0;
  55.  
  56.     //grab the DC from the surface
  57.     HDC hdc;
  58.     lpddsTileSet->GetDC(&hdc);
  59.  
  60.     //temp variables for control colors
  61.     COLORREF crTransparent=GetPixel(hdc,iWidth-1,0);
  62.     COLORREF crWall=GetPixel(hdc,iWidth-1,1);
  63.     COLORREF crAnchor=GetPixel(hdc,iWidth-1,2);
  64.     COLORREF crInside=GetPixel(hdc,iWidth-1,3);
  65.     COLORREF crInsideAnchor=GetPixel(hdc,iWidth-1,4);
  66.     COLORREF crTest=RGB(0,0,0);
  67.  
  68.     //count the number of vertical cell walls
  69.     //by scanning the top pixel row
  70.     VCellWallCount=0;
  71.     for(xCount=0;xCount<iWidth;xCount++)
  72.     {
  73.         //retrieve the pixel
  74.         crTest=GetPixel(hdc,xCount,0);
  75.  
  76.         //test for transparent color
  77.         if(crTest==crTransparent)
  78.         {
  79.             //increase wall counter
  80.             VCellWallCount++;
  81.         }
  82.     }
  83.  
  84.     //allocate the vertical cell wall list
  85.     VCellWall=new int[VCellWallCount];
  86.     
  87.     //find vertical cell walls
  88.     VCellWallCount=0;
  89.     for(xCount=0;xCount<iWidth;xCount++)
  90.     {
  91.         //retrieve the pixel
  92.         crTest=GetPixel(hdc,xCount,0);
  93.  
  94.         //test for transparent color
  95.         if(crTest==crTransparent)
  96.         {
  97.             //add x value to the list
  98.             VCellWall[VCellWallCount]=xCount;
  99.  
  100.             //increase wall counter
  101.             VCellWallCount++;
  102.         }
  103.     }
  104.  
  105.     //count the number of vertical cell walls
  106.     //by scanning the top pixel row
  107.     HCellWallCount=0;
  108.     for(yCount=0;yCount<iHeight;yCount++)
  109.     {
  110.         //retrieve the pixel
  111.         crTest=GetPixel(hdc,0,yCount);
  112.  
  113.         //test for transparent color
  114.         if(crTest==crTransparent)
  115.         {
  116.             //increase wall counter
  117.             HCellWallCount++;
  118.         }
  119.     }
  120.  
  121.     //allocate the vertical cell wall list
  122.     HCellWall=new int[HCellWallCount];
  123.     
  124.     //find vertical cell walls
  125.     HCellWallCount=0;
  126.     for(yCount=0;yCount<iHeight;yCount++)
  127.     {
  128.         //retrieve the pixel
  129.         crTest=GetPixel(hdc,0,yCount);
  130.  
  131.         //test for transparent color
  132.         if(crTest==crTransparent)
  133.         {
  134.             //add x value to the list
  135.             HCellWall[HCellWallCount]=yCount;
  136.  
  137.             //increase wall counter
  138.             HCellWallCount++;
  139.         }
  140.     }
  141.  
  142.     //calculate number of rows, number of columns, and number of tiles
  143.     int tilerows=HCellWallCount-1;
  144.     int tilecolumns=VCellWallCount-1;
  145.     int tilenum=0;
  146.     dwTileCount=tilerows*tilecolumns;
  147.  
  148.     //allocate tile list
  149.     ptiTileList=new TILEINFO[dwTileCount];
  150.  
  151.     //scan all tiles
  152.     for(int rowcount=0;rowcount<tilerows;rowcount++)
  153.     {
  154.         for(int columncount=0;columncount<tilecolumns;columncount++)
  155.         {
  156.             //tile number
  157.             tilenum=columncount+rowcount*tilecolumns;
  158.  
  159.             //temporary flag variable
  160.             bool found=false;
  161.  
  162.             //scan top
  163.             yCount=HCellWall[rowcount];
  164.  
  165.             //scan top for anchor
  166.             found=false;
  167.             for(xCount=VCellWall[columncount]+1;(!found)&&(xCount<VCellWall[columncount+1]-1);xCount++)
  168.             {
  169.                 //grab pixel
  170.                 crTest=GetPixel(hdc,xCount,yCount);
  171.  
  172.                 //check pixel for anchor
  173.                 if((crTest==crAnchor) || (crTest==crInsideAnchor))
  174.                 {
  175.                     found=true;
  176.                     ptiTileList[tilenum].ptAnchor.x=xCount;
  177.                 }
  178.             }
  179.  
  180.             //scan top for first inside pixel
  181.             found=false;
  182.             for(xCount=VCellWall[columncount]+1;(!found)&&(xCount<VCellWall[columncount+1]-1);xCount++)
  183.             {
  184.                 //grab pixel
  185.                 crTest=GetPixel(hdc,xCount,yCount);
  186.  
  187.                 //check pixel for anchor
  188.                 if((crTest==crInside) || (crTest==crInsideAnchor))
  189.                 {
  190.                     found=true;
  191.                     ptiTileList[tilenum].rcSrc.left=xCount;
  192.                 }
  193.             }
  194.  
  195.             //not found, use default
  196.             if(!found)
  197.             {
  198.                 ptiTileList[tilenum].rcSrc.left=VCellWall[columncount]+1;
  199.             }
  200.  
  201.             //scan top for last inside pixel
  202.             found=false;
  203.             for(xCount=VCellWall[columncount+1]-1;(!found)&&(xCount>=VCellWall[columncount]+1);xCount--)
  204.             {
  205.                 //grab pixel
  206.                 crTest=GetPixel(hdc,xCount,yCount);
  207.  
  208.                 //check pixel for anchor
  209.                 if((crTest==crInside) || (crTest==crInsideAnchor))
  210.                 {
  211.                     found=true;
  212.                     ptiTileList[tilenum].rcSrc.right=xCount+1;
  213.                 }
  214.             }
  215.  
  216.             //not found, use default
  217.             if(!found)
  218.             {
  219.                 ptiTileList[tilenum].rcSrc.left=VCellWall[columncount+1];
  220.             }
  221.  
  222.             //scan left
  223.             xCount=VCellWall[columncount];
  224.  
  225.             //scan left for anchor
  226.             found=false;
  227.             for(yCount=HCellWall[rowcount]+1;(!found)&&(yCount<HCellWall[rowcount+1]-1);yCount++)
  228.             {
  229.                 //grab pixel
  230.                 crTest=GetPixel(hdc,xCount,yCount);
  231.  
  232.                 //check pixel for anchor
  233.                 if((crTest==crAnchor) || (crTest==crInsideAnchor))
  234.                 {
  235.                     found=true;
  236.                     ptiTileList[tilenum].ptAnchor.y=yCount;
  237.                 }
  238.             }
  239.  
  240.             //scan left for first inside pixel
  241.             found=false;
  242.             for(yCount=HCellWall[rowcount]+1;(!found)&&(yCount<HCellWall[rowcount+1]-1);yCount++)
  243.             {
  244.                 //grab pixel
  245.                 crTest=GetPixel(hdc,xCount,yCount);
  246.  
  247.                 //check pixel for anchor
  248.                 if((crTest==crInside) || (crTest==crInsideAnchor))
  249.                 {
  250.                     found=true;
  251.                     ptiTileList[tilenum].rcSrc.top=yCount;
  252.                 }
  253.             }
  254.  
  255.             //not found, use default
  256.             if(!found)
  257.             {
  258.                 ptiTileList[tilenum].rcSrc.top=HCellWall[rowcount]+1;
  259.             }
  260.  
  261.             //scan left for last inside pixel
  262.             found=false;
  263.             for(yCount=HCellWall[rowcount+1]-1;(!found)&&(yCount>=HCellWall[rowcount]+1);yCount--)
  264.             {
  265.                 //grab pixel
  266.                 crTest=GetPixel(hdc,xCount,yCount);
  267.  
  268.                 //check pixel for anchor
  269.                 if((crTest==crInside) || (crTest==crInsideAnchor))
  270.                 {
  271.                     found=true;
  272.                     ptiTileList[tilenum].rcSrc.bottom=yCount+1;
  273.                 }
  274.             }
  275.  
  276.             //not found, use default
  277.             if(!found)
  278.             {
  279.                 ptiTileList[tilenum].rcSrc.bottom=HCellWall[rowcount+1];
  280.             }
  281.  
  282.             //calculate the destination extents
  283.             CopyRect(&ptiTileList[tilenum].rcDstExt,&ptiTileList[tilenum].rcSrc);
  284.             OffsetRect(&ptiTileList[tilenum].rcDstExt,-ptiTileList[tilenum].ptAnchor.x,-ptiTileList[tilenum].ptAnchor.y);
  285.  
  286.         }
  287.     }
  288.  
  289.     //release the dc of the surface
  290.     lpddsTileSet->ReleaseDC(hdc);
  291.  
  292.     //set the transparent color
  293.     LPDDS_SetSrcColorKey(lpddsTileSet,ConvertColorRef(crTransparent,&ddsd.ddpfPixelFormat));
  294. }
  295.  
  296. //reload(restore)
  297. void CTileSet::Reload()
  298. {
  299.     //reload image
  300.     LPDDS_ReloadFromFile(lpddsTileSet,lpszReload);
  301. }
  302.  
  303. //unload(uninitializer)
  304. void CTileSet::Unload()
  305. {
  306.     //safely release the tile list
  307.     if(ptiTileList)
  308.     {
  309.         delete [] ptiTileList;
  310.         ptiTileList=NULL;
  311.         dwTileCount=0;
  312.     }
  313.  
  314.     //release the surface
  315.     LPDDS_Release(&lpddsTileSet);
  316.  
  317.     //release the file name
  318.     if(lpszReload)
  319.     {
  320.         free(lpszReload);
  321.         lpszReload=NULL;
  322.     }
  323. }
  324.  
  325. //get number of tiles
  326. DWORD CTileSet::GetTileCount()
  327. {
  328.     //return the tile count
  329.     return(dwTileCount);
  330. }
  331.  
  332. //get tile list
  333. TILEINFO* CTileSet::GetTileList()
  334. {
  335.     //return the beginning of the tile list
  336.     return(ptiTileList);
  337. }
  338.  
  339. //get surface
  340. LPDIRECTDRAWSURFACE7 CTileSet::GetDDS()
  341. {
  342.     //return the source surface
  343.     return(lpddsTileSet);
  344. }
  345.  
  346. //retrieve filename
  347. LPSTR CTileSet::GetFileName()
  348. {
  349.     //return the file name
  350.     return(lpszReload);
  351. }
  352.  
  353. //blit a tile
  354. void CTileSet::PutTile(LPDIRECTDRAWSURFACE7 lpddsDst,int xDst,int yDst,int iTileNum)
  355. {
  356.     //offset the desired tile's extent
  357.     OffsetRect(&ptiTileList[iTileNum].rcDstExt,xDst,yDst);
  358.     //blit the tile
  359.     lpddsDst->Blt(&ptiTileList[iTileNum].rcDstExt,lpddsTileSet,&ptiTileList[iTileNum].rcSrc,DDBLT_WAIT | DDBLT_KEYSRC,NULL);
  360.     //offset the desired tile's extent back
  361.     OffsetRect(&ptiTileList[iTileNum].rcDstExt,-xDst,-yDst);
  362. }
  363.  
  364.